const EvalTool = B.EvalTool;

let intervalLog;

let arrStint = [];

const updateStint = function(itemStint, now) {
	const { typeTiming, timeBase, interval, render } = itemStint;
	let { timeNext } = itemStint;

	if(!timeNext || timeNext.isSameOrBefore(now, 's')) {
		if(typeTiming == 1) {
			const diff = Math.abs(timeBase.diff(now, 's'));
			const tickNext = Math.floor(diff / interval) + 1;

			itemStint.text.desc = render(now.format());

			itemStint.timeNext = timeNext = timeBase.clone().add(tickNext * interval, 's');
		}
	}

	itemStint.text.remain = EvalTool.tiffText(timeNext, now);
};

const isNum = (text) => /^([1-9]\d*(\.\d+)*|0[xo]\d+)$/.test(text);
// const convertValue = (v) => {
// 	let t = `'${v}'`;

// 	if(isNum(v)) {
// 		t = v;
// 	}
// 	else if(typeof v == 'object' && v) {
// 		t = JSON.stringify(v);
// 	}

// 	return t;
// };
const run = function(expression, ...arrEnvs) {
	// const { tadd, tiff, tiffText, Q } = ET;
	// const env = arrEnvs.map(envs => Object.entries(envs).map(([k, v]) => `const ${k} = ${convertValue(v)};`).join('')).join('');
	// return eval(`{${env} (${main});}`);

	return Function('$', `return ${expression.replace(/\\#|#/g, (match) => match == '#' ? '$.' : '#')};`)(
		arrEnvs.reduce((acc, cur) => (Object.entries(cur).forEach(([k, v]) => acc[k] = isNum(v) ? Number(v) : v) || true) && acc, {})
	);
};

export const Timing = {
	log: (now = M()) => B.arrStint.forEach(({ arrItem }) => arrItem.forEach(item => updateStint(item, now))),

	init: (arrStint_ = B.D.arrStint) => {
		arrStint = [...arrStint_];

		for(const stint of arrStint) {
			Vue.set(stint, 'paramTexts', stint.paramTexts || {});

			for(const item of stint.arrItem) {
				const envStint = { interval: item.interval, timeBase: item.timeBase };
				const envParams = item.params;

				item.timeBase = M(item.timeBase);

				Vue.set(item, 'paramTexts', item.paramTexts || {});
				Vue.set(item, 'isShowParams', false);
				Vue.set(item, 'text', { remain: '', text: '' });
				Vue.set(item, 'render', (tnow = M().format()) => {
					const envDynamic = {};

					for(const [id, calc] of Object.entries(item.calcs)) {
						envDynamic[id] = run(calc, EvalTool, { tnow }, envStint, envParams, envDynamic);
					}

					for(const [cond, template] of item.template.arrCond) {
						if(run(cond, EvalTool, envStint, envParams, envDynamic)) {
							return run(`\`${template}\``, EvalTool, { tnow }, envStint, envParams, envDynamic);
						}
					}

					return run(`\`${item.template.default}\``, EvalTool, { tnow }, envStint, envParams, envDynamic);
				});
			}
		}
	},

	go: () => intervalLog = setInterval(Timing.log, 1000),
	stop: () => clearInterval(intervalLog)
};